package com.polytech.diploma.StatAccumulator;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import com.polytech.diploma.OracleStat.SQLStatData;
import com.polytech.diploma.StatAccumulator.Comparator.DurationStatComparator;
import com.polytech.diploma.StatAccumulator.Comparator.GeneralCostComparator;
import com.polytech.diploma.StatAccumulator.Comparator.IOStatComparator;
import com.polytech.diploma.StatAccumulator.Comparator.MemoryStatComparator;
import com.polytech.diploma.StatAccumulator.Comparator.RowsProcessedComparator;

public class OracleStatAccumulator {
	
	private static OracleStatAccumulator oracleStatAccumulator = null;
	
	private OracleStatAccumulator() {	}
	
	public static OracleStatAccumulator getInstance()
	{
		if(oracleStatAccumulator==null)
			oracleStatAccumulator = new OracleStatAccumulator();
		return oracleStatAccumulator;
	}
	
	public Set<SQLStatData> doStatAccumulation (Set<SQLStatData> statData, StatPercentage statPercentage)
	{
		Set<SQLStatData> resultSet = new HashSet<SQLStatData>();
		
		int queryLimit = (int) statPercentage.getTotalNum();
		
		if(queryLimit==0)
			queryLimit = (int) statPercentage.getTotalNumPercents() * statData.size();
		
		resultSet.addAll(this.getMaxQueries(	statData,
												new MemoryStatComparator(),
												(int)(statPercentage.getMaxMemory()*queryLimit)));
		
		resultSet.addAll(this.getMaxQueries(	statData,
												new IOStatComparator(),
												(int)(statPercentage.getMaxIO()*queryLimit)));

		resultSet.addAll(this.getMaxQueries(	statData, 
												new GeneralCostComparator(),
												(int)(statPercentage.getMaxCost()*queryLimit)));

		resultSet.addAll(this.getMaxQueries(	statData, 
												new DurationStatComparator(),
												(int)(statPercentage.getMaxDuration()*queryLimit)));
				
		resultSet.addAll(this.getMaxQueries(	statData, 
												new RowsProcessedComparator(),
												(int)(statPercentage.getMaxMPRows()*queryLimit)));
		
		return resultSet;
	}
	
	protected Set<SQLStatData> getMaxQueries(Set<SQLStatData> statData, 
												Comparator<SQLStatData> comparator, 
												int queryLimit)
	{
		if (queryLimit==0 || statData.size()==0)
		{
			return Collections.emptySet();
		}
		
		Set<SQLStatData> tempSet = new TreeSet<SQLStatData>(comparator);
		Set<SQLStatData> resultSet = new TreeSet<SQLStatData>(comparator);
		
		for(SQLStatData stat : statData)
		{
			tempSet.add(
					new SQLStatData.SQLStatDataBuilder()
							.setSqlText(stat.getSqlText())
							.setCount(stat.getCount())
							.setRuntimeMemory(stat.getRuntimeMemory()/stat.getCount())
							.setPersistentMemory(stat.getPersistentMemory()/stat.getCount())											
							.setDiskReads(stat.getDiskReads()/stat.getCount())											
							.setBufferGets(stat.getBufferGets()/stat.getCount())										
							.setUserIOWaitTime(stat.getUserIOWaitTime()/stat.getCount())											
							.setRowsProcessed(stat.getRowsProcessed()/stat.getCount())
							.setOptimizerCost(stat.getOptimizerCost()/stat.getCount())										
							.setElapsedTime(stat.getElapsedTime()/stat.getCount())
							.setFirstLoadTime(stat.getFirstLoadTime())
							.setCommandType(stat.getCommandType().getCmdType())
							.setReplaceList(stat.getReplaceMap())
							.build());
		}
		
		Iterator<SQLStatData> statIterator = tempSet.iterator();
		
		for(int i=0; statIterator.hasNext() && i<queryLimit; i++)
		{
			resultSet.add(statIterator.next());
		}
		
		statData.removeAll(resultSet);
		
		return resultSet;
	}
}
